﻿using System;
using System.Collections.Generic;
using System.Linq;
using CCS;
using CCSTest.Properties;
using Microsoft.Samples.ServiceHosting.StorageClient;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace CCSTest
{
    [TestClass]
    public class MigrationTests
    {
        #region Setup Code

        private readonly StorageAccountInfo accountInfo = new StorageAccountInfo(Settings.Default.TableStorageEndpoint,
                                                                                 true, Settings.Default.AccountName,
                                                                                 Settings.Default.AccountSharedKey);

        private readonly Guid devToken = Guid.NewGuid();
        private readonly TableStorage tableStorage;

        public MigrationTests()
        {
            tableStorage = TableStorage.Create(accountInfo);
            tableStorage.RetryPolicy = RetryPolicies.RetryN(10, TimeSpan.FromSeconds(1));
        }

        private CCSProduct _GetProduct()
        {
            CCSProduct retval = Procedures.InsertNewProduct(tableStorage,
                                                            string.Format("Test {0}", DateTime.UtcNow.Ticks),
                                                            DateTime.Now.AddDays(3), Guid.NewGuid().ToString(), 3, 0, 0,
                                                            0, 0, 0, devToken);
            Assert.IsNotNull(retval);
            return retval;
        }


        private string _GetInvoice(CCSProduct product)
        {
            CCSLicenseLevelPrice licenseLevelPrice = Procedures.GetProductLicenseLevels(accountInfo, product.ProductName,
                                                                                        product.DevToken);
            Assert.IsNotNull(licenseLevelPrice);

            string invoice = Guid.NewGuid().ToString();

            CCSLicenseTransaction licenseTransaction = Procedures.StoreLicenseTransaction(tableStorage, invoice,
                                                                                          string.Empty, product.ID,
                                                                                          licenseLevelPrice.LicenseID,
                                                                                          product.DevToken, string.Empty);
            Assert.IsNotNull(licenseTransaction);

            PaymentTransaction paymentTransaction = Procedures.Payment_Insert_Transaction(tableStorage, DateTime.Now,
                                                                                          string.Empty,
                                                                                          Guid.NewGuid().ToString(),
                                                                                          licenseTransaction.Invoice,
                                                                                          string.Empty, 0, 0,
                                                                                          string.Empty, DateTime.Now,
                                                                                          "completed", string.Empty,
                                                                                          string.Empty, string.Empty,
                                                                                          string.Empty, 0, 0,
                                                                                          string.Empty, 0, string.Empty,
                                                                                          string.Empty);
            Assert.IsNotNull(paymentTransaction);

            PaymentShoppingItems paymentShoppingItems = Procedures.Payment_Insert_Shopping_Items(tableStorage,
                                                                                                 paymentTransaction.ID,
                                                                                                 product.ProductName,
                                                                                                 product.ID.ToString(),
                                                                                                 string.Empty,
                                                                                                 string.Empty,
                                                                                                 string.Empty,
                                                                                                 string.Empty);
            Assert.IsNotNull(paymentShoppingItems);

            PaymentCustInfo paymentCustInfo = Procedures.Payment_Insert_CustInfo(tableStorage, paymentTransaction.ID,
                                                                                 "114 Alaskan Way South #104",
                                                                                 string.Empty, "Office", string.Empty,
                                                                                 string.Empty, "Seattle", "US",
                                                                                 "206-409-9940", string.Empty,
                                                                                 string.Empty, "tyler@hotmethod.com",
                                                                                 "Tyler", "Schlegel", string.Empty,
                                                                                 string.Empty, string.Empty,
                                                                                 string.Empty, string.Empty, "WA",
                                                                                 "98104");
            Assert.IsNotNull(paymentCustInfo);

            return paymentTransaction.Invoice;
        }

        #endregion

        /// <summary>
        /// Replacing SP "AddUserInfo"
        /// </summary>
        [TestMethod]
        public void Replaced_AddUserInfo()
        {
            // Get test product?
            CCSProduct product = _GetProduct();

            // Create user?
            CCSUser user = Procedures.AddUserInfo(accountInfo, tableStorage, "Schlegel", "Tyler",
                                                  "114 Alaskan Way South #104", "Seattle", "WA", "98104", "206-409-4900",
                                                  "tyler@hotmethod.com", product.DevToken, product.ProductName,
                                                  "Shareware", Guid.NewGuid().ToString());
            Assert.IsNotNull(user);
        }

        /// <summary>
        /// Replacing SP "CreatePaymentSettings"
        /// </summary>
        [TestMethod]
        public void Replaced_CreatePaymentSettings()
        {
            CCSProduct product = _GetProduct();

            CCSPaymentSettings paymentSettings = Procedures.CreatePaymentSettings(tableStorage, product.DevToken,
                                                                                  string.Empty, string.Empty, 0,
                                                                                  string.Empty, string.Empty, true, true,
                                                                                  string.Empty, string.Empty,
                                                                                  string.Empty, string.Empty,
                                                                                  string.Empty, string.Empty);
            Assert.IsNotNull(paymentSettings);
        }

        /// <summary>
        /// Replacing SP "GetAllowedInvoiceCount"
        /// </summary>
        [TestMethod]
        public void Replaced_GetAllowedInvoiceCount()
        {
            CCSProduct product = _GetProduct();

            CCSLicenseLevelPrice licenseLevelPrice = Procedures.GetProductLicenseLevels(accountInfo, product.ProductName,
                                                                                        product.DevToken);
            Assert.IsNotNull(licenseLevelPrice);

            string invoice = Guid.NewGuid().ToString();
            CCSLicenseTransaction licenseTransaction = Procedures.StoreLicenseTransaction(tableStorage, invoice,
                                                                                          string.Empty, product.ID,
                                                                                          licenseLevelPrice.LicenseID,
                                                                                          product.DevToken, string.Empty);
            Assert.IsNotNull(licenseTransaction);

            int licenseCount = Procedures.GetAllowedInvoiceCount(accountInfo, tableStorage, invoice);

            Assert.AreEqual(3, licenseCount);
        }

        /// <summary>
        /// Replacing SP "GetApprovedInvoiceCount"
        /// </summary>
        [TestMethod]
        public void Replaced_GetApprovedInvoiceCount()
        {
            CCSProduct product = _GetProduct();

            CCSLicenseLevelPrice licenseLevelPrice = Procedures.GetProductLicenseLevels(accountInfo, product.ProductName,
                                                                                        product.DevToken);
            Assert.IsNotNull(licenseLevelPrice);

            string invoice = Guid.NewGuid().ToString();
            CCSLicenseTransaction licenseTransaction = Procedures.StoreLicenseTransaction(tableStorage, invoice,
                                                                                          string.Empty, product.ID,
                                                                                          licenseLevelPrice.LicenseID,
                                                                                          product.DevToken, string.Empty);
            licenseTransaction.LicenseResponse = "approved";
            licenseTransaction.Update(tableStorage, CCSLicenseTransaction.TableName);

            Assert.IsNotNull(licenseTransaction);

            int approvedInvoiceCount = Procedures.GetApprovedInvoiceCount(accountInfo, invoice);

            Assert.AreEqual(1, approvedInvoiceCount);
        }

        /// <summary>
        /// Replacing SP "GetProductConfigSettings"
        /// </summary>
        [TestMethod]
        public void Replaced_GetProductConfigSettings()
        {
            CCSProduct product = _GetProduct();

            CCSProductConfigSettings productConfigSettings = Procedures.GetProductConfigSettings(accountInfo,
                                                                                                 product.ProductName,
                                                                                                 product.DevToken);
            Assert.IsNotNull(productConfigSettings);
        }

        /// <summary>
        /// Replacing SP "GetProductDataStoreSettings"
        /// </summary>
        [TestMethod]
        public void Replaced_GetProductDataStoreSettings()
        {
            CCSProduct product = _GetProduct();
            CCSLicenseLevelPrice licenseLevelPrice = Procedures.GetProductLicenseLevels(accountInfo, product.ProductName,
                                                                                        product.DevToken);
            Assert.IsNotNull(licenseLevelPrice);
            string machineId = Guid.NewGuid().ToString();
            Procedures.InitializeProductDataStoreSettings(tableStorage, accountInfo, product.DevToken, DateTime.Now,
                                                          product.ProductName, licenseLevelPrice.LicenseLevel, 0,
                                                          string.Empty, DateTime.Now, false, machineId);
            CCSProductDataStore productDataStore = Procedures.GetProductDataStoreSettings(accountInfo, product.DevToken,
                                                                                          product.ProductName, machineId);
            Assert.IsNotNull(productDataStore);
        }

        /// <summary>
        /// Replacing SP "GetProductLicenseLevels"
        /// </summary>
        [TestMethod]
        public void Replaced_GetProductLicenseLevels()
        {
            CCSProduct product = _GetProduct();

            CCSLicenseLevelPrice licenseLevelPrice = Procedures.GetProductLicenseLevels(accountInfo, product.ProductName,
                                                                                        product.DevToken);
            Assert.IsNotNull(licenseLevelPrice);
        }

        /// <summary>
        /// Replacing SP "GetProductPaymentSettings"
        /// </summary>
        [TestMethod]
        public void Replaced_GetProductPaymentSettings()
        {
            CCSProduct product = _GetProduct();
            Procedures.CreatePaymentSettings(tableStorage, product.DevToken, string.Empty, string.Empty, 0, string.Empty,
                                             string.Empty, true, true, string.Empty, string.Empty, string.Empty,
                                             string.Empty, string.Empty, string.Empty);
            CCSPaymentSettings paymentSettings = Procedures.GetProductPaymentSettings(accountInfo, product.DevToken);
            Assert.IsNotNull(paymentSettings);
        }

        /// <summary>
        /// Replacing SP "GetTrialLicenseLevel"
        /// </summary>
        [TestMethod]
        public void Replaced_GetTrialLicenseLevel()
        {
            CCSProduct product = _GetProduct();
            CCSLicenseLevelPrice licenseLevel = Procedures.GetTrialLicenseLevel(accountInfo, product.ProductName,
                                                                                product.DevToken);
            Assert.IsNotNull(licenseLevel);
        }

        /// <summary>
        /// Replacing SP "InitializeProductDataStoreSettings
        /// </summary>
        [TestMethod]
        public void Replaced_InitializeProductDataStoreSettings()
        {
            CCSProduct product = _GetProduct();

            CCSProductDataStore productDataStore = Procedures.InitializeProductDataStoreSettings(tableStorage,
                                                                                                 accountInfo,
                                                                                                 product.DevToken,
                                                                                                 DateTime.Now,
                                                                                                 product.ProductName,
                                                                                                 "Shareware", 10,
                                                                                                 string.Empty,
                                                                                                 DateTime.Now, true,
                                                                                                 Guid.NewGuid().ToString
                                                                                                     ());
            Assert.IsNotNull(productDataStore);
        }

        /// <summary>
        /// Replacing SP "InsertNewProduct"
        /// </summary>
        [TestMethod]
        public void Replaced_InsertNewProduct()
        {
            // Create product?
            CCSProduct product = Procedures.InsertNewProduct(tableStorage,
                                                             string.Format("Test {0}", DateTime.UtcNow.Ticks),
                                                             DateTime.Now.AddDays(3), Guid.NewGuid().ToString(), 1, 0, 0,
                                                             0, 0, 0, devToken);
            Assert.IsNotNull(product);

            // Created config for product?
            var productConfigSettingsServiceContext = new CCSProductConfigSettingsServiceContext(accountInfo);
            CCSProductConfigSettings productConfigSettings =
                productConfigSettingsServiceContext.CCSProductConfigSettings.Where(
                    f => f.PartitionKey == CCSProductConfigSettings.TableName && f.ProductID == product.ID).
                    FirstOrDefault();
            Assert.IsNotNull(productConfigSettings);

            // Created three license levels for product?
            var licenseLevelPriceServiceContext = new CCSLicenseLevelPriceServiceContext(accountInfo);
            IQueryable<CCSLicenseLevelPrice> licenseLevelPrices =
                licenseLevelPriceServiceContext.CCSLicenseLevelPrices.Where(
                    f => f.PartitionKey == CCSLicenseLevelPrice.TableName && f.ProductID == product.ID);
            Assert.AreEqual(3, licenseLevelPrices.ToArray().Length);
        }

        /// <summary>
        /// Replacing SP "InvoiceInPaymentTransaction"
        /// </summary>
        [TestMethod]
        public void Replaced_InvoiceInPaymentTransaction()
        {
            string invoice = _GetInvoice(_GetProduct());
            PaymentTransaction invoiceInPaymentTransaction = Procedures.InvoiceInPaymentTransaction(accountInfo, invoice);
            Assert.IsNotNull(invoiceInPaymentTransaction);
        }

        /// <summary>b
        /// Replacing SP "IsInvoiceACoupon"
        /// </summary>
        [TestMethod]
        public void Replaced_IsInvoiceACoupon()
        {
            CCSProduct product = _GetProduct();
            string invoice = _GetInvoice(product);
            Assert.IsFalse(string.IsNullOrEmpty(invoice));

            CCSLicenseLevelPrice licenseLevelPrice =
                Procedures.Get<CCSLicenseLevelPrice>(new CCSLicenseLevelPriceServiceContext(accountInfo),
                                                     new Dictionary<string, object>
                                                         {
                                                             {"ProductID", product.ID},
                                                             {"DevToken", product.DevToken},
                                                             {"TrialLicenseKey", true}
                                                         }).Single();
            _CreateCoupon(invoice, devToken, licenseLevelPrice.LicenseID);

            IEnumerable<CCSCoupon> coupons = Procedures.IsInvoiceACoupon(accountInfo, invoice, product.DevToken);
            Assert.IsTrue(coupons.Count() > 0);
        }

        /// <summary>
        /// Replacing SP "MarkInvoice"
        /// </summary>
        [TestMethod]
        public void Replaced_MarkInvoice()
        {
            string invoice = _GetInvoice(_GetProduct());
            Assert.IsFalse(string.IsNullOrEmpty(invoice));

            Procedures.MarkInvoice(tableStorage, accountInfo, invoice, string.Empty);
        }

        /// <summary>
        /// Replacing SP "Payment_Insert_CustInfo"
        /// </summary>
        [TestMethod]
        public void Replaced_Payment_Insert_CustInfo()
        {
            PaymentCustInfo paymentCustInfo = Procedures.Payment_Insert_CustInfo(tableStorage, Guid.NewGuid(),
                                                                                 "114 Alaskan Way South #104",
                                                                                 string.Empty, "Office", string.Empty,
                                                                                 string.Empty, "Seattle", "US",
                                                                                 "425-231-6082", string.Empty,
                                                                                 string.Empty, "tyler@hotmethod.com",
                                                                                 "Tyler", "Schlegel", string.Empty,
                                                                                 string.Empty, string.Empty,
                                                                                 string.Empty, string.Empty, "WA",
                                                                                 "98104");
            Assert.IsNotNull(paymentCustInfo);
        }

        /// <summary>
        /// Replacing SP "Payment_Insert_Shopping_Items"
        /// </summary>
        [TestMethod]
        public void Replaced_Payment_Insert_Shopping_Items()
        {
            CCSProduct product = _GetProduct();
            PaymentShoppingItems paymentShoppingItems = Procedures.Payment_Insert_Shopping_Items(tableStorage,
                                                                                                 product.ID,
                                                                                                 string.Empty,
                                                                                                 string.Empty,
                                                                                                 string.Empty,
                                                                                                 string.Empty,
                                                                                                 string.Empty,
                                                                                                 string.Empty);
            Assert.IsNotNull(paymentShoppingItems);
        }

        /// <summary>
        /// Replacing SP "Payment_Insert_Transaction"
        /// </summary>
        [TestMethod]
        public void Replaced_Payment_Insert_Transaction()
        {
            CCSProduct product = _GetProduct();

            PaymentTransaction paymentTransaction = Procedures.Payment_Insert_Transaction(tableStorage, DateTime.Now,
                                                                                          string.Empty,
                                                                                          product.DevToken.ToString(),
                                                                                          string.Empty, string.Empty,
                                                                                          0.00, 0.00, string.Empty,
                                                                                          DateTime.Now, string.Empty,
                                                                                          string.Empty, string.Empty,
                                                                                          string.Empty, string.Empty, 0,
                                                                                          0.00, string.Empty, 0.00,
                                                                                          string.Empty, string.Empty);
            Assert.IsNotNull(paymentTransaction);
        }

        /// <summary>
        /// Replacing SP "Payment_Insert_Transaction_Related"
        /// </summary>
        [TestMethod]
        public void Replaced_Payment_Insert_Transaction_Related()
        {
            CCSProduct product = _GetProduct();

            PaymentTransaction paymentTransaction = Procedures.Payment_Insert_Transaction(tableStorage, DateTime.Now,
                                                                                          string.Empty,
                                                                                          product.DevToken.ToString(),
                                                                                          string.Empty, string.Empty,
                                                                                          0.00, 0.00, string.Empty,
                                                                                          DateTime.Now, string.Empty,
                                                                                          string.Empty, string.Empty,
                                                                                          string.Empty, string.Empty, 0,
                                                                                          0.00, string.Empty, 0.00,
                                                                                          string.Empty, string.Empty);
            Assert.IsNotNull(paymentTransaction);

            PaymentTransactionRelated paymentTransactionRelated =
                Procedures.Payment_Insert_Transaction_Related(tableStorage, paymentTransaction.ID, 0.0, string.Empty,
                                                              string.Empty, string.Empty, string.Empty, string.Empty,
                                                              string.Empty, string.Empty, string.Empty, string.Empty,
                                                              string.Empty, DateTime.UtcNow, string.Empty, string.Empty);
            Assert.IsNotNull(paymentTransactionRelated);
        }

        /// <summary>
        /// Replacing SP "PaymentCompletedTransactions"
        /// </summary>
        [TestMethod]
        public void Replaced_PaymentCompletedTransactions()
        {
            string invoice = _GetInvoice(_GetProduct());
            Assert.IsFalse(string.IsNullOrEmpty(invoice));

            int paymentCompletedTransactions = Procedures.PaymentCompletedTransactions(accountInfo);
            Assert.IsTrue(paymentCompletedTransactions > 0);
        }

        /// <summary>
        /// Replacing SP "SendMailApprovedLicense"
        /// </summary>
        [TestMethod]
        public void Replaced_SendMailApprovedLicense()
        {
            string invoice = _GetInvoice(_GetProduct());
            Assert.IsFalse(string.IsNullOrEmpty(invoice));
            Procedures.SendMailApprovedLicense(tableStorage, accountInfo, invoice);
        }

        /// <summary>
        /// Replacing SP "SetCouponDate"
        /// </summary>
        [TestMethod]
        public void Replaced_SetCouponDate()
        {
            CCSProduct product = _GetProduct();
            string invoice = _GetInvoice(product);
            Assert.IsFalse(string.IsNullOrEmpty(invoice));
            CCSLicenseLevelPrice licenseLevel = Procedures.GetProductLicenseLevels(accountInfo, product.ProductName,
                                                                                   product.DevToken);
            CCSCoupon coupon = _CreateCoupon(invoice, product.DevToken, licenseLevel.LicenseID);

            Procedures.SetCouponDate(tableStorage, accountInfo, invoice);
        }

        private CCSCoupon _CreateCoupon(string invoice, Guid devToken, Guid licenseLevel)
        {
            var coupon = new CCSCoupon(CCSCoupon.TableName, Extensions.DefaultRowKey().ToString())
                             {
                                 Coupon_number = new Guid(invoice),
                                 Created_date = DateTime.Now,
                                 DevToken = devToken,
                                 License_level = licenseLevel,
                                 ID = Guid.NewGuid().GetHashCode(),
                                 Used_date = TableStorageConstants.MinSupportedDateTime
                             };
            bool saved = coupon.Save(tableStorage, CCSCoupon.TableName, CCSCoupon.TableName);
            if (!saved)
            {
                throw new CCSEntitySaveException();
            }
            return coupon;
        }

        /// <summary>
        /// Replacing SP "StoreAuthLicense"
        /// </summary>
        [TestMethod]
        public void Replaced_StoreAuthLicense()
        {
            string invoice = _GetInvoice(_GetProduct());
            Procedures.StoreAuthLicense(tableStorage, accountInfo, invoice, string.Empty);
        }

        /// <summary>
        /// Replacing SP "StoreLicenseTransaction"
        /// </summary>
        [TestMethod]
        public void Replaced_StoreLicenseTransaction()
        {
            CCSProduct product = _GetProduct();

            CCSLicenseLevelPrice licenseLevelPrice = Procedures.GetProductLicenseLevels(accountInfo, product.ProductName,
                                                                                        product.DevToken);
            Assert.IsNotNull(licenseLevelPrice);

            string invoice = Guid.NewGuid().ToString();
            CCSLicenseTransaction licenseTransaction = Procedures.StoreLicenseTransaction(tableStorage, invoice,
                                                                                          string.Empty, product.ID,
                                                                                          licenseLevelPrice.LicenseID,
                                                                                          product.DevToken, string.Empty);
            Assert.IsNotNull(licenseTransaction);
        }

        /// <summary>
        /// Replacing SP "SubmitException"
        /// </summary>
        [TestMethod]
        public void Replaced_SubmitException()
        {
            CCSProduct product = _GetProduct();
            Procedures.SubmitException(tableStorage, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty,
                                       product.DevToken, string.Empty, string.Empty);
        }

        /// <summary>
        /// Replacing SP "SubmitIssue"
        /// </summary>
        [TestMethod]
        public void Replaced_SubmitIssue()
        {
            CCSProduct product = _GetProduct();
            CCSLicenseLevelPrice licenseLevelPrice = Procedures.GetProductLicenseLevels(accountInfo, product.ProductName,
                                                                                        product.DevToken);
            CCSIssue issue = Procedures.SubmitIssue(tableStorage, accountInfo, product.ProductName,
                                                    licenseLevelPrice.LicenseLevel, "tyler@hotmethod.com", "Tyler",
                                                    "Schlegel", string.Empty, product.DevToken,
                                                    Guid.NewGuid().ToString());
        }

        /// <summary>
        /// Replacing SP "UpdateDataStoreRegistration"
        /// </summary>
        [TestMethod]
        public void Replaced_UpdateDataStoreRegistration()
        {
            CCSProduct product = _GetProduct();
            CCSLicenseLevelPrice licenseLevelPrice = Procedures.GetProductLicenseLevels(accountInfo, product.ProductName,
                                                                                        product.DevToken);
            string machineId = Guid.NewGuid().ToString();
            CCSProductDataStore productDataStore = Procedures.InitializeProductDataStoreSettings(tableStorage,
                                                                                                 accountInfo,
                                                                                                 product.DevToken,
                                                                                                 DateTime.Now,
                                                                                                 product.ProductName,
                                                                                                 licenseLevelPrice.
                                                                                                     LicenseLevel, 0,
                                                                                                 string.Empty,
                                                                                                 DateTime.Now, false,
                                                                                                 machineId);
            bool updated = Procedures.UpdateDataStoreRegistration(tableStorage, accountInfo, product.DevToken,
                                                                  product.ProductName, productDataStore.UniqueMachineID,
                                                                  true,
                                                                  licenseLevelPrice.LicenseLevel);
            Assert.IsTrue(updated);
        }

        /// <summary>
        /// Replacing SP "UpdateDataStoreRegistrationKey"
        /// </summary>
        [TestMethod]
        public void Replaced_UpdateDataStoreRegistrationKey()
        {
            CCSProduct product = _GetProduct();
            CCSLicenseLevelPrice licenseLevelPrice = Procedures.GetProductLicenseLevels(accountInfo, product.ProductName,
                                                                                        product.DevToken);
            CCSProductDataStore productDataStore = Procedures.InitializeProductDataStoreSettings(tableStorage,
                                                                                                 accountInfo,
                                                                                                 product.DevToken,
                                                                                                 DateTime.UtcNow,
                                                                                                 product.ProductName,
                                                                                                 licenseLevelPrice.
                                                                                                     LicenseLevel, 0,
                                                                                                 string.Empty,
                                                                                                 DateTime.UtcNow, true,
                                                                                                 Guid.NewGuid().ToString
                                                                                                     ());
            Procedures.UpdateDataStoreRegistrationKey(tableStorage, accountInfo, productDataStore.DevToken,
                                                      product.ProductName, Guid.NewGuid().ToString(),
                                                      licenseLevelPrice.LicenseLevel);
        }

        /// <summary>
        /// Replacing SP "UpdateProductSettings"
        /// </summary>
        [TestMethod]
        public void Replaced_UpdateProductSettings()
        {
            CCSProduct product = _GetProduct();
            Procedures.UpdateProductSettings(tableStorage, accountInfo, product.ProductName, DateTime.Now, string.Empty,
                                             0, product.ID, 0, 0, 0, 0, 0);
        }
    }
}